#ifndef __PROC_H_
#define __PROC_H_

#include "types.h"
#include "trap.h"
#include "page.h"

#define MAX_PROC_NUM 10
#define PROC_FD_NUM 10

struct context {
	// return address
	uint64 ra;
	// proc stack pointer
	uint64 sp;
	uint64 s0;
	uint64 s1;
	uint64 s2;
	uint64 s3;
	uint64 s4;
	uint64 s5;
	uint64 s6;
	uint64 s7;
	uint64 s8;
	uint64 s9;
	uint64 s10;
	uint64 s11;
};

enum proc_state
{
      UNINIT, RUNNABLE, RUNNING, ZOMBIE, SLEEPING
};

struct proc {
	// user proc's pid always > 0
	int pid;
	enum proc_state state;
	struct trapframe *tf_ptr;
	struct context *con_ptr;
	struct pgtable_l3 *table_ptr3;
	// virtual memory address
	struct vma *vma_list;
	// process's parent process
	struct proc *parent_ptr;
	struct zombie *zombie_child_list;
	// file descriptors
	struct file_info *fd_table[PROC_FD_NUM];
};

struct zombie {
	struct linked_list *next;
	struct proc *proc_ptr;
	// exit value
	int exit_val;
};

struct scheduler {
	void (*init)(void);
	struct proc *(*next_proc)(void);
	void (*runnable)(struct proc *proc_in);
};

// from proc.c
// pointer of proc being running
extern struct proc *cur_proc;
extern struct proc *init_proc;
void proc_init();
struct proc *alloc_proc();
int alloc_fd();
void init_fd_table(struct file_info *fd_table[]);
void free_fd_table(struct file_info *fd_table[]);
void copy_segments(struct vma *vma_ptr, struct pgtable_l3 *table_ptr3);
void free_vma_list(struct vma** vma_ptr);
void proc_switch();
void run_proc(struct proc* proc_ptr);
int proc_clone(uint64 flags, uint64 stack, uint64 ptid, uint64 tls, uint64 ctid);
int proc_execve(char *path, char * argv[], char *envp[]);
int proc_wait(int pid, int *code, int options);
void proc_exit(int ec);
// from context.S
extern void context_switch(struct context *from, struct context *to);
extern void context_switch_ret();



#endif
